package com.winning.sjzc.common.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;

/**
 * description:APP登录Token的生成和解析
 *
 * @author yanxf@winning.com.cn
 * @date 2019/08/13 18:11
 */
public class JwtToken {
  /**
   * token秘钥，请勿泄露，请勿随便修改 backups:JKKLJOoasdlfj
   */
  public static final String SECRET = "JKKLJOoasdlfj";

  public static Date getExpireTime(String type) {
    Date expiresDate = null;
    if (!StringUtils.isEmpty(type) && type.equals("b")) {
      Calendar nowTime = Calendar.getInstance();
      nowTime.add(Calendar.HOUR, 8);
      expiresDate = nowTime.getTime();
    } else if (!StringUtils.isEmpty(type) && type.equals("f")) {
      Calendar nowTime = Calendar.getInstance();
      nowTime.add(Calendar.DAY_OF_YEAR, 99999999);
      expiresDate = nowTime.getTime();
    }
    return expiresDate;
  }

  /**
   * 获取请求的token
   */
  public static String getRequestToken(HttpServletRequest httpRequest) {
    //从header中获取token
    String token = httpRequest.getHeader("token");

    //如果header中不存在token，则从参数中获取token
    if (StringUtils.isBlank(token)) {
      token = httpRequest.getParameter("token");
    }
    return token;
  }

  /**
   * JWT生成Token
   * JWT构成: header, payload, signature
   *
   * @param zclsh
   * @return
   * @throws Exception
   */
  public static String createToken(String zclsh) throws Exception {
    Map<String, String> map = new HashMap<>();
    map.put("zclsh", zclsh);
    return createToken(map);
  }

  /**
   * JWT生成Token
   * JWT构成: header, payload, signature
   *
   * @param zclsh
   * @return
   * @throws Exception
   */
  public static String createToken(String zclsh, String jgbm) throws Exception {
    Map<String, String> map = new HashMap<>();
    map.put("zclsh", zclsh);
    map.put("jgbm", jgbm);
    return createToken(map);
  }

  public static String createToken(Map<String, String> keyMap) throws Exception {
    Date iatDate = new Date();
    // header Map
    Map<String, Object> configMap = new HashMap<>();
    configMap.put("alg", "HS256");
    configMap.put("typ", "JWT");
    JWTCreator.Builder tokenBudile = JWT.create().withHeader(configMap);// header
    for (String key : keyMap.keySet()) {
      tokenBudile.withClaim(key, keyMap.get(key));
    }
    String token = tokenBudile.withIssuedAt(iatDate) // sign time
        .withExpiresAt(getExpireTime("b")) // expire time
        .sign(Algorithm.HMAC256(SECRET)); // signature
    return token;
  }

  /**
   * 解密Token
   *
   * @param token
   * @return
   * @throws Exception
   */
  public static Map<String, Claim> verifyToken(String token) throws UnsupportedEncodingException, JWTVerificationException {
    DecodedJWT jwt = null;
    JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
    jwt = verifier.verify(token);
    return jwt.getClaims();
  }

  /**
   * 判断Token是否过期
   *
   * @param token
   * @return
   * @throws Exception
   */
  public static Boolean tokenIsExpire(String token) throws JWTDecodeException, UnsupportedEncodingException {
    Map<String, Claim> stringClaimMap = verifyToken(token);
    Date exp = stringClaimMap.get("exp").asDate();
    Date now = new Date();
    if (exp.getTime() - now.getTime() < 0)
      return true;
    return false;
  }

  /**
   * 根据Token获取user_id
   *
   * @param token
   * @return user_id
   */
  public static Long getZclsh(String token) {
    Map<String, Claim> claims = null;
    try {
      claims = verifyToken(token);
    } catch (UnsupportedEncodingException e) {

    }
    Claim user_id_claim = claims.get("zclsh");
    if (null == user_id_claim || StringUtils.isEmpty(user_id_claim.asString())) {

    }
    return Long.valueOf(user_id_claim.asString());
  }

  public static void main(String[] args) throws Exception {
    String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrc2JtIjoiIiwib3JnbmFtZSI6Iua1meaxn-ecgeWNq-eUn-WSjOiuoeWIkuWxgCIsIm9yZ2NvZGUiOiIwMDI0ODIzNjUzMzAxMDMxMVA5MTcxIiwienlnaCI6IiIsImtzbWMiOiIiLCJleHAiOjE1NTE3ODE4NTMsInpjbHNoIjoiOTAwNjI3Q0EtOENCMi00Q0QyLTg4NzItNTk2RTU5RURDMjhDIiwienl4bSI6Iui2hee6p-euoeeQhuWRmCIsImlhdCI6MTU1MTc1MzA1M30.gqQwAUTjx5Kh-Wa5e8qtwWFN_eDQErOSAZkG2cn_gU4";

    Map<String, Claim> aaa = verifyToken(token);

    for (String key : aaa.keySet()) {
      System.out.println(key + "---" + aaa.get(key).asString());
    }
  }
}
